#ifndef COMMON_STRING_TOKENIZER_H_
#define COMMON_STRING_TOKENIZER_H_
#include <vector>
#include <string>
#include <cstddef>
#include <assert.h>


#pragma GCC diagnostic ignored "-Wshadow"
/*!
* This is not the most efficent way to split the string,
* eg. map the spliters two a ascii map [1-255] and index it 
* directly will be more quick than this way.
*/
namespace fermat {

/*!
* A simple tokenizer that splits a string into
* tokens, which are separated by separator characters.
* An iterator is used to iterate over all tokens.
*/
class  StringTokenizer {
public:
	enum Options
	{
		TOK_IGNORE_EMPTY = 1, //< ignore empty tokens
		TOK_TRIM	 = 2  //< remove leading and trailing whitespace from tokens
	};
	
	typedef std::vector<std::string> TokenVec;
	typedef TokenVec::const_iterator Iterator;

	/*!
	* Splits the given string into tokens. The tokens are expected to be
	* separated by one of the separator characters given in separators.
	* Additionally, options can be specified:
	*   * TOK_IGNORE_EMPTY: empty tokens are ignored
	*   * TOK_TRIM: trailing and leading whitespace is removed from tokens.
	*/
	StringTokenizer(const std::string& str, const std::string& separators, int options = 0);

	/*!
	* Destroys the tokenizer.
	*/
	~StringTokenizer();
		
	
	Iterator begin() const;
	Iterator end() const;

	/*!
	*@return const reference the index'th token.
	*/
	const std::string& operator [] (std::size_t index) const;
		
	/*!	
	* Returns reference to the index'th token.
	*/
	std::string& operator [] (std::size_t index);
		
	/*!		
	* @return true if token exists, false otherwise.
	*/
	bool has(const std::string& token) const;
		
	/*!		
	* @return the index of the first occurence of the token
	* starting at position pos.
	*/
	std::string::size_type find(const std::string& token, std::string::size_type pos = 0) const;

	/*!	
	* @brief Starting at position pos, replaces all subsequent tokens having value 
	* equal to oldToken with newToken.
	* @return the number of modified tokens.
	*/
	std::size_t replace(const std::string& oldToken, const std::string& newToken, std::string::size_type pos = 0);

	/*!
	* Returns the total number of tokens.
	*/	
	std::size_t count() const;

	/*!		
	*@return the number of tokens equal to the specified token.
	*/
	std::size_t count(const std::string& token) const;
		

private:
	StringTokenizer(const StringTokenizer&);
	StringTokenizer& operator = (const StringTokenizer&);
	
	void trim(std::string& token);

	TokenVec _tokens;
};


//
// inlines
//


inline StringTokenizer::Iterator StringTokenizer::begin() const
{
	return _tokens.begin();
}


inline StringTokenizer::Iterator StringTokenizer::end() const
{
	return _tokens.end();
}


inline std::string& StringTokenizer::operator [] (std::size_t index)
{
	if (index >= _tokens.size()) {
		assert(false);
	}
	return _tokens[index];
}


inline const std::string& StringTokenizer::operator [] (std::size_t index) const
{
	if (index >= _tokens.size()) {
		assert(false);
	}
	return _tokens[index];
}


inline std::size_t StringTokenizer::count() const
{
	return _tokens.size();
}


} 

#endif
